
import sys, os
import pygst
pygst.require("0.10")
import gst
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade


PIPELINE = """filesrc location=%s ! mad ! alsasink device=hw:0"""  


class SFX:
    def __init__(self):
        self.pads = {}
        gladeFile = os.path.join(os.path.dirname(__file__,), 'sfx.glade') 
        self.xml = gtk.glade.XML(gladeFile, None) 
        self.xml.signal_autoconnect(self) 
        window = self.xml.get_widget("main") 
        table = self.xml.get_widget("soundTable")
        self.playingButton = self.xml.get_widget("playingButton")
        self.createButtons(table, open(sys.argv[1]).readlines())
        window.connect('delete-event', gtk.main_quit) 
        window.show_all() 
        self.pipeline = gst.Pipeline("pipeline0")
        self.bus = self.pipeline.get_bus()   
        self.bus.add_watch(self.busMessage)    
        self.adder = gst.element_factory_make("adder")
        self.volume = gst.element_factory_make("volume")
        sink = gst.element_factory_make("alsasink")
        sink.set_property("device", "hw:0")
        self.pipeline.add(self.adder, self.volume, sink)
        gst.element_link_many(self.adder, self.volume, sink)

    def on_volumeScale_change_value(self, w, e, volume):
        self.volume.set_property('volume', volume/100.0)

    def padEvent(self, pad, event):
        if event.type == gst.EVENT_EOS:
            filename, filesrc, mad, audioconvert = self.pads.get(pad)
            audioconvert.unlink(self.adder)
            self.pipeline.remove(filesrc, mad, audioconvert)
        return True

    def busMessage(self, bus, message):
        if message.type == gst.MESSAGE_EOS:
            self.playingButton.set_active(False)
        return True

    def createButtons(self, table, sounds):
        from math import sqrt
        # Try to create a square array of buttons
        nrows = int(sqrt(len(sounds)))+1
        ncols = (len(sounds)/nrows) + 1
        table.resize(nrows, ncols)
        sounds = [s.strip().split(':',1) for s in sounds]
        for i, (name, filename) in enumerate(sounds):
            button = gtk.Button("%02d %s"%(i, name,))
            button.set_events(gtk.gdk.BUTTON_PRESS_MASK)
            button.connect("event",  
                        lambda w,e,f=filename: self.buttonPress(w,e,f))
            row = i % ncols
            col = i / ncols
            table.attach(button,row,row+1,col,col+1)
            button.show()

    def buttonPress(self, widget, event, filename):
        if event.type != gtk.gdk.BUTTON_PRESS:
            return
        if event.button == 1:
            self.playSound(filename)

    def playSound(self, filename):
        filesrc = gst.element_factory_make('filesrc')
        filesrc.set_property("location", filename)
        mad = gst.element_factory_make('mad')
        audioconvert = gst.element_factory_make('audioconvert')
        self.pipeline.add(filesrc, mad, audioconvert)
        gst.element_link_many(filesrc, mad, audioconvert)
        acpad = audioconvert.get_pad('src')
        addpad = self.adder.get_request_pad('sink%d')
        acpad.link(addpad)
        addpad.add_event_probe(self.padEvent)
        self.pads[addpad] = (filename, filesrc, mad, audioconvert)

        self.playingButton.set_active(True)
        self.pipeline.set_state(gst.STATE_PLAYING)

    def on_quit_activate(self, widget):
        gtk.main_quit()


if __name__ == "__main__":
    gui=SFX()
    gtk.main() 
